
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link href='/css/styles.css' rel='stylesheet' type='text/css' />
    <link href='/images/favicon.png' rel='shortcut icon' />
    <script src='/js/jquery.min.1.4.js'></script>
    <script src='/js/app.js'></script>
    <meta content='width=device-width, minimum-scale=1.0, maximum-scale=1.0' name='viewport' />
    <title>Redis命令</title>
	<meta http-equiv="description" content="nosql-redis中文站，redis国内官方网站，Redis全部命令介绍" />
	
  </head>
  <body class=''>
    <script src='/js/head.js'></script>
	<div class='text'>
      <article id='topic'>
        <aside>
          <h2>
            Related commands
          </h2>
          <ul>
            <li>
              <a href='/commands/discard'>DISCARD</a>
            </li>
            <li>
              <a href='/commands/exec'>EXEC</a>
            </li>
            <li>
              <a href='/commands/multi'>MULTI</a>
            </li>
            <li>
              <a href='/commands/unwatch'>UNWATCH</a>
            </li>
            <li>
              <a href='/commands/watch'>WATCH</a>
            </li>
          </ul>
        </aside>
    <h1>Transactions</h1>
        
        <p><a href="/commands/multi">MULTI</a>, <a href="/commands/exec">EXEC</a>, <a href="/commands/discard">DISCARD</a> and <a href="/commands/watch">WATCH</a> are the foundation of
        transactions in Redis.  They allow the execution of a group of commands
        in a single step, with two important guarantees:</p>
        
        <ul>
        <li><p>All the commands in a transaction are serialized and executed
        sequentially. It can never happen that a request issued by another
        client is served <strong>in the middle</strong> of the execution of a Redis
        transaction. This guarantees that the commands are executed as a single
        atomic operation.</p></li>
        <li><p>Either all of the commands or none are processed. The <a href="/commands/exec">EXEC</a> command
        triggers the execution of all the commands in the transaction, so
        if a client loses the connection to the server in the context of a
        transaction before calling the <a href="/commands/multi">MULTI</a> command none of the operations
        are performed, instead if the <a href="/commands/exec">EXEC</a> command is called, all the
        operations are performed. When using the
        <a href="/topics/persistence#append-only-file">append-only file</a> Redis makes sure
        to use a single write(2) syscall to write the transaction on disk.
        However if the Redis server crashes or is killed by the system administrator
        in some hard way it is possible that only a partial number of operations
        are registered. Redis will detect this condition at restart, and will exit with an error. Using the <code>redis-check-aof</code> tool it is possible to fix the
        append only file that will remove the partial transaction so that the
        server can start again.</p></li>
        </ul>
        
        
        <p>Redis 2.2 allows for an extra guarantee to the above two, in the form
        of optimistic locking in a way very similar to a check-and-set (CAS)
        operation. This is documented <a href="#cas">later</a> on this page.</p>
        
        <h2>Usage</h2>
        
        <p>A Redis transaction is entered using the <a href="/commands/multi">MULTI</a> command. The command
        always replies with <code>OK</code>. At this point the user can issue multiple
        commands. Instead of executing these commands, Redis will queue
        them. All the commands are executed once <a href="/commands/exec">EXEC</a> is called.</p>
        
        <p>Calling <a href="/commands/discard">DISCARD</a> instead will flush the transaction queue and will exit
        the transaction.</p>
        
        <p>The following example increments keys <code>foo</code> and <code>bar</code> atomically.</p>
        
        <pre><code>&gt; MULTI&#x000A;OK&#x000A;&gt; INCR foo&#x000A;QUEUED&#x000A;&gt; INCR bar&#x000A;QUEUED&#x000A;&gt; EXEC&#x000A;1) (integer) 1&#x000A;2) (integer) 1&#x000A;</code></pre>
        
        <p>As it is possible to see from the session above, <a href="/commands/multi">MULTI</a> returns an
        array of replies, where every element is the reply of a single command
        in the transaction, in the same order the commands were issued.</p>
        
        <p>When a Redis connection is in the context of a <a href="/commands/multi">MULTI</a> request,
        all commands will reply with the string <code>QUEUED</code> unless they are
        syntactically incorrect. Some commands are still allowed to fail during
        execution time.</p>
        
        <p>This is more clear on the protocol level. In the following example one
        command will fail when executed even if the syntax is right:</p>
        
        <pre><code>Trying 127.0.0.1...&#x000A;Connected to localhost.&#x000A;Escape character is '^]'.&#x000A;MULTI&#x000A;+OK&#x000A;SET a 3&#x000A;abc&#x000A;+QUEUED&#x000A;LPOP a&#x000A;+QUEUED&#x000A;EXEC&#x000A;*2&#x000A;+OK&#x000A;-ERR Operation against a key holding the wrong kind of value&#x000A;</code></pre>
        
        <p><a href="/commands/multi">MULTI</a> returned two-element <a href="/topics/protocol#bulk-reply">Bulk reply</a> where one is an <code>OK</code> code and
        the other an <code>-ERR</code> reply. It's up to the client library to find a
        sensible way to provide the error to the user.</p>
        
        <p>It's important to note that <strong>even when a command fails, all the other
        commands in the queue are processed</strong> – Redis will <em>not</em> stop the
        processing of commands.</p>
        
        <p>Another example, again using the wire protocol with <code>telnet</code>, shows how
        syntax errors are reported ASAP instead:</p>
        
        <pre><code>MULTI&#x000A;+OK&#x000A;INCR a b c&#x000A;-ERR wrong number of arguments for 'incr' command&#x000A;</code></pre>
        
        <p>This time due to the syntax error the bad <a href="/commands/incr">INCR</a> command is not queued
        at all.</p>
        
        <h2>Discarding the command queue</h2>
        
        <p><a href="/commands/discard">DISCARD</a> can be used in order to abort a transaction. In this case, no
        commands are executed and the state of the connection is restored to
        normal.</p>
        
        <pre><code>&gt; SET foo 1&#x000A;OK&#x000A;&gt; MULTI&#x000A;OK&#x000A;&gt; INCR foo&#x000A;QUEUED&#x000A;&gt; DISCARD&#x000A;OK&#x000A;&gt; GET foo&#x000A;"1"&#x000A;</code></pre>
        
        <p><a name="cas"></a></p>
        
        <h2>Optimistic locking using check-and-set</h2>
        
        <p><a href="/commands/watch">WATCH</a> is used to provide a check-and-set (CAS) behavior to Redis
        transactions.</p>
        
        <p><code>WATCH</code>ed keys are monitored in order to detect changes against them. If
        at least one watched key is modified before the <a href="/commands/exec">EXEC</a> command, the
        whole transaction aborts, and <a href="/commands/exec">EXEC</a> returns a <a href="/topics/protocol#nil-reply">Null multi-bulk reply</a> to notify that
        the transaction failed.</p>
        
        <p>For example, imagine we have the need to atomically increment the value
        of a key by 1 (let's suppose Redis doesn't have <a href="/commands/incr">INCR</a>).</p>
        
        <p>The first try may be the following:</p>
        
        <pre><code>val = GET mykey&#x000A;val = val + 1&#x000A;SET mykey $val&#x000A;</code></pre>
        
        <p>This will work reliably only if we have a single client performing the
        operation in a given time. If multiple clients try to increment the key
        at about the same time there will be a race condition. For instance,
        client A and B will read the old value, for instance, 10. The value will
        be incremented to 11 by both the clients, and finally <a href="/commands/set">SET</a> as the value
        of the key. So the final value will be 11 instead of 12.</p>
        
        <p>Thanks to <a href="/commands/watch">WATCH</a> we are able to model the problem very well:</p>
        
        <pre><code>WATCH mykey&#x000A;val = GET mykey&#x000A;val = val + 1&#x000A;MULTI&#x000A;SET mykey $val&#x000A;EXEC&#x000A;</code></pre>
        
        <p>Using the above code, if there are race conditions and another client
        modifies the result of <code>val</code> in the time between our call to <a href="/commands/watch">WATCH</a> and
        our call to <a href="/commands/exec">EXEC</a>, the transaction will fail.</p>
        
        <p>We just have to repeat the operation hoping this time we'll not get a
        new race. This form of locking is called <em>optimistic locking</em> and is
        a very powerful form of locking. In many use cases, multiple clients
        will be accessing different keys, so collisions are unlikely – usually
        there's no need to repeat the operation.</p>
        
        <h2><a href="/commands/watch">WATCH</a> explained</h2>
        
        <p>So what is <a href="/commands/watch">WATCH</a> really about? It is a command that will
        make the <a href="/commands/exec">EXEC</a> conditional: we are asking Redis to perform
        the transaction only if no other client modified any of the
        <code>WATCH</code>ed keys. Otherwise the transaction is not entered at
        all. (Note that if you <a href="/commands/watch">WATCH</a> a volatile key and Redis expires
        the key after you <code>WATCH</code>ed it, <a href="/commands/exec">EXEC</a> will still work. <a href="http://code.google.com/p/redis/issues/detail?id=270">More on
        this</a>.)</p>
        
        <p><a href="/commands/watch">WATCH</a> can be called multiple times. Simply all the <a href="/commands/watch">WATCH</a> calls will
        have the effects to watch for changes starting from the call, up to
        the moment <a href="/commands/exec">EXEC</a> is called. You can also send any number of keys to a
        single <a href="/commands/watch">WATCH</a> call.</p>
        
        <p>When <a href="/commands/exec">EXEC</a> is called, all keys are <code>UNWATCH</code>ed, regardless of whether
        the transaction was aborted or not.  Also when a client connection is
        closed, everything gets <code>UNWATCH</code>ed.</p>
        
        <p>It is also possible to use the <a href="/commands/unwatch">UNWATCH</a> command (without arguments)
        in order to flush all the watched keys. Sometimes this is useful as we
        optimistically lock a few keys, since possibly we need to perform a
        transaction to alter those keys, but after reading the current content
        of the keys we don't want to proceed.  When this happens we just call
        <a href="/commands/unwatch">UNWATCH</a> so that the connection can already be used freely for new
        transactions.</p>
        
        <h3>Using <a href="/commands/watch">WATCH</a> to implement ZPOP</h3>
        
        <p>A good example to illustrate how <a href="/commands/watch">WATCH</a> can be used to create new
        atomic operations otherwise not supported by Redis is to implement ZPOP,
        that is a command that pops the element with the lower score from a
        sorted set in an atomic way. This is the simplest implementation:</p>
        
        <pre><code>WATCH zset&#x000A;element = ZRANGE zset 0 0&#x000A;MULTI&#x000A;ZREM zset element&#x000A;EXEC&#x000A;</code></pre>
        
        <p>If <a href="/commands/exec">EXEC</a> fails (i.e. returns a <a href="/topics/protocol#nil-reply">Null multi-bulk reply</a>) we just repeat the operation.</p>
      </article>
    </div>
    <div class='text' id='comments'>
      <div id='disqus_thread'></div>
      <script type='text/javascript'>
        //<![CDATA[
          var disqus_shortname = 'rediscn';
          
          /* * * DON'T EDIT BELOW THIS LINE * * */
          (function() {
            var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
              dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
              (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
          })();
        //]]>
      </script>
      <a class='dsq-brlink' href='http://disqus.com'>
        Comments powered by
        <span class='logo-disqus'>
          Disqus
        </span>
      </a>
    </div>
    <script src='/js/foot.js'></script>
  </body>
</html>
